package app.engine.mc;

import app.engine.entitys.Move;
import app.game.enums.Chess;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class MCTreeNode {

    // 当前节点对应的局面
    public Chess[][] chessBoard;
    // 当前节点的局面下一手棋颜色
    public Chess nowChess;
    // 当前节点局面的衍生决策
    public Move move;
    // 当前节点的累计收益
    public double value = 0d;
    // 当前节点累计遍历次数
    public double times = 0d;
    // 子节点
    public List<MCTreeNode> childrenList;
    // 父节点
    public MCTreeNode parent;
    public boolean isActive = false;
    public double finalFlag = -999;

    public static MCTreeNode buildRootNode(Chess[][] chessBoard, Chess comChess) {
        MCTreeNode root = new MCTreeNode();
        root.chessBoard = chessBoard;
        root.nowChess = comChess;
        root.activeNode(comChess);
        return root;
    }

    public void activeNode(Chess comChess) {
        this.isActive = true;
        if (this.move != null && SearchHelper.isEnd(this.chessBoard, this.move, this.nowChess.getReverse())) {
            finalFlag = this.nowChess.getReverse() == comChess ? 1 : -1;
            return;
        }
        List<MCTreeNode> cList = new ArrayList<>();
        List<Move> moves = SearchHelper.getMoves(this.chessBoard, this.nowChess);
        if (moves.size() <= 0) {
            finalFlag = 0;
            return;
        }
        moves.sort(new Comparator<Move>() {
            @Override
            public int compare(Move o1, Move o2) {
                return o2.getScore() - o1.getScore();
            }
        });
        for (Move move : moves) {
            MCTreeNode c = new MCTreeNode();
            c.chessBoard = SearchHelper.copyChessBoard(chessBoard);
            c.chessBoard[move.getX()][move.getY()] = this.nowChess;
            c.nowChess = this.nowChess.getReverse();
            c.parent = this;
            c.move = move;
            cList.add(c);
        }
        this.childrenList = cList;
    }

    public double getUCBValue(double total, boolean maxFlag) {
        if (maxFlag) {
            return this.value / this.times + MCTreeSearchEngine.ucbParam * (Math.sqrt(2 * Math.log(total) / this.times));
        }
        return this.value / this.times - MCTreeSearchEngine.ucbParam * (Math.sqrt(2 * Math.log(total) / this.times));
    }

    @Override
    public String toString() {
        return nowChess.getName() + ":" + (move != null ? move.toString() : "") + " 累计得分:" + value + " 遍历次数:" + times;
    }
}
